package com.lglbc.grpcbootchat;

import com.lglbc.chatroom.Chat;
import com.lglbc.chatroom.ChatServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;

import java.util.concurrent.ConcurrentHashMap;

@GrpcService
public class ChatServiceImpl extends ChatServiceGrpc.ChatServiceImplBase {

    private final ConcurrentHashMap<String, StreamObserver<Chat.ChatMessage>> userObservers = new ConcurrentHashMap<>();

    @Override
    public StreamObserver<Chat.JoinRequest> joinRoom(StreamObserver<Chat.ChatMessage> responseObserver) {
        return new StreamObserver<Chat.JoinRequest>() {
            private String username;

            @Override
            public void onNext(Chat.JoinRequest joinRequest) {
                username = joinRequest.getUsername();
                userObservers.put(username, responseObserver);

                broadcastMessage(username, "joined the room.");
            }

            @Override
            public void onError(Throwable t) {
                userObservers.remove(username);
                broadcastMessage(username, "left the room.");
            }

            @Override
            public void onCompleted() {
                userObservers.remove(username);
                broadcastMessage(username, "left the room.");
                responseObserver.onCompleted();
            }
        };
    }

    @Override
    public void sendMessage(Chat.ChatMessage request, StreamObserver<Chat.Empty> responseObserver) {
        String message = "[" + request.getUsername() + "]: " + request.getMessage();
        broadcastMessage(request.getUsername(), message);
        responseObserver.onNext(Chat.Empty.getDefaultInstance());
        responseObserver.onCompleted();
    }

    private void broadcastMessage(String username, String message) {
        Chat.ChatMessage chatMessage = Chat.ChatMessage.newBuilder()
                .setUsername(username)
                .setMessage(message)
                .build();

        for (StreamObserver<Chat.ChatMessage> observer : userObservers.values()) {
            observer.onNext(chatMessage);
        }
    }
}
